---
title: 插件方法
description: 探索可用于扩展Plate插件的各种方法。
---

## 配置方法

扩展插件时，默认情况下所有属性都会进行深度合并，但有两个例外：数组会被完全替换，而`options`对象会进行浅合并。

### .configure

`.configure`方法允许你覆盖插件的配置。

```ts
const ConfiguredPlugin = MyPlugin.configure({
  options: {
    myOption: 'new value',
  },
});
```

你也可以使用函数来访问当前配置：

```ts
const ConfiguredPlugin = MyPlugin.configure(({ getOptions }) => ({
  options: {
    ...getOptions(),
    myOption: `${getOptions().myOption} + extra`,
  },
}));
```

- 用于修改插件的现有属性
- 不会向插件添加新属性
- 最后应用的配置会被编辑器使用
- 不返回扩展类型，保持原始插件类型

### .configurePlugin

`.configurePlugin`方法允许你配置嵌套插件的属性：

```ts
const TablePlugin = createPlatePlugin({
  key: 'table',
  plugins: [TableCellPlugin],
}).configurePlugin(TableCellPlugin, {
  options: {
    cellOption: 'modified',
  },
});
```

- 用于配置父插件中的嵌套插件
- 与`.configure`类似，修改现有属性但不添加新属性
- 适合在不扩展子插件类型的情况下调整其行为

### .extend

`.extend`方法允许你扩展插件的配置和功能。

```ts
const ExtendedPlugin = MyPlugin.extend({
  options: {
    newOption: 'new value',
  },
});
```

你也可以使用函数来访问当前配置和编辑器：

```ts
const ExtendedPlugin = MyPlugin.extend(({ editor, plugin }) => ({
  options: {
    newOption: 'new value',
  },
  handlers: {
    onKeyDown: () => {
      // 自定义按键逻辑
    },
  },
}));
```

- 用于向插件添加新属性或修改现有属性
- 返回具有扩展类型的新插件实例
- 支持链式调用，允许多个扩展顺序应用

### .extendPlugin

`.extendPlugin`方法允许你扩展嵌套插件的配置和功能：

```ts
const TablePlugin = createPlatePlugin({
  key: 'table',
  plugins: [TableCellPlugin],
}).extendPlugin(TableCellPlugin, {
  options: {
    newCellOption: 'added',
  },
  handlers: {
    onKeyDown: () => {
      // 表格单元格的自定义按键逻辑
    },
  },
});
```

- 用于扩展父插件中的嵌套插件
- 可以向嵌套插件添加新属性并修改现有属性
- 返回包含扩展嵌套插件的新父插件实例

### .configure与.extend的区别

虽然这两种方法都可以用于修改插件配置，但存在一些关键差异：

1. 链式调用：`.extend`支持链式调用，而`.configure`不支持
2. 类型扩展：`.extend`返回具有扩展类型的新插件实例，而`.configure`保持原始类型
3. 新属性：`.extend`可以向插件配置添加新属性，而`.configure`仅修改现有属性

根据是否需要扩展插件类型和功能（使用`.extend`）或仅修改现有配置（使用`.configure`）来选择适当的方法。

### .extendSelectors

`extendSelectors`方法允许你向插件添加可订阅的选择器：

```ts
const CounterPlugin = createPlatePlugin({
  key: 'counter',
  options: {
    count: 0,
  },
}).extendSelectors(({ getOptions }) => ({
  doubleCount: () => getOptions().count * 2,
  isEven: () => getOptions().count % 2 === 0,
}));
```

然后你可以在组件或其他插件方法中使用这些选择器：

```tsx
const CounterComponent = () => {
  const count = usePluginOption(CounterPlugin, 'count');
  const doubleCount = usePluginOption(CounterPlugin, 'doubleCount');
  const isEven = usePluginOption(CounterPlugin, 'isEven');

  return (
    <div>
      <p>Count: {count}</p>
      <p>Double Count: {doubleCount}</p>
      <p>Is Even: {isEven ? 'Yes' : 'No'}</p>
    </div>
  );
};
```

- 允许你从插件选项创建派生状态或计算值
- 使用`getOption`读取值
- 使用`usePluginOption`订阅值，当选项变化时重新计算，仅在结果变化时重新渲染。**这是与`.extendApi`的主要区别**

### .withComponent

`withComponent`方法允许你设置或替换与插件关联的组件。

```ts
const ParagraphPlugin = createPlatePlugin({
  key: 'p',
  node: {
    isElement: true,
    type: 'p',
  },
}).withComponent(ParagraphElement);
```

## API和转换方法

插件可以定义自己的API方法和转换方法，这些方法将被合并到编辑器的API和转换中。这是通过`extendApi`、`extendEditorApi`、`extendTransforms`和`extendEditorTransforms`方法实现的。

### .extendApi

使用`extendApi`添加插件特定的API方法：

```ts
const MyPlugin = createPlatePlugin({
  key: 'myPlugin',
}).extendApi(() => ({
  pluginMethod: () => 'plugin method result',
}));

// 访问插件的API
editor.api.myPlugin.api.pluginMethod();
```

### .extendEditorApi

使用`extendEditorApi`添加根级API方法：

```ts
const MyPlugin = createPlatePlugin({
  key: 'myPlugin',
}).extendEditorApi(({ getOptions }) => ({
  editorMethod: () => getOptions().someOption,
}));

// 访问插件的API
editor.api.editorMethod();
```

### .extendTransforms

使用`extendTransforms`添加插件特定的转换方法：

```ts
const MyPlugin = createPlatePlugin({
  key: 'myPlugin',
}).extendTransforms(() => ({
  pluginTransform: () => {
    // 自定义转换逻辑
  },
}));

// 访问插件的转换方法
editor.tf.myPlugin.pluginTransform();

// 注意：`editor.tf`是`editor.transforms`的简写
editor.transforms.myPlugin.pluginTransform();
```

### .extendEditorTransforms

使用`extendEditorTransforms`添加根级转换方法：

```ts
const MyPlugin = createPlatePlugin({
  key: 'myPlugin',
}).extendEditorTransforms(({ editor }) => ({
  editorTransform: () => {
    // 自定义编辑器转换逻辑
  },
}));

// 访问插件的转换方法
editor.tf.editorTransform();
```

### .overrideEditor

`overrideEditor`方法专门用于在不改变插件类型的情况下覆盖现有的编辑器方法：

```ts
const MyPlugin = createPlatePlugin({
  key: 'myPlugin',
}).overrideEditor(({ editor, tf: { insertText }, api: { isInline } }) => ({
  transforms: {
    insertText(text, options) {
      // 覆盖insertText行为
      insertText(text, options);
    },
  },
  api: {
    isInline(element) {
      // 覆盖isInline行为
      return isInline(element);
    },
  },
}));
```

- 专门用于覆盖现有的编辑器方法
- 返回包装在`transforms`或`api`对象中的重写方法
- 不能添加新方法（使用`extendEditorTransforms`或`extendEditorApi`替代）
- 通过上下文提供对原始方法的访问

### API与转换方法的区别

虽然目前Plate中API和转换方法在核心上没有区别，但它们服务于不同的目的，并为未来的可扩展性而设计：

- **转换方法：**
  - 存储所有Slate转换和编辑器操作。结构设计为未来可能支持中间件，允许更复杂的转换管道和开发工具。
  - 通常用于修改编辑器状态的操作，如插入、删除或转换内容。
  - 示例：`editor.tf.toggleBlock()`、`editor.tf.toggleMark('bold')`

- **API方法：**
  - 存储所有查询、实用函数和其他不直接修改编辑器状态的方法。
  - 示例：`editor.api.save()`、`editor.api.debug.log()`

### 链式扩展

你可以链式调用这些方法来创建全面的插件：

```ts
const MyPlugin = createPlatePlugin({
  key: 'myPlugin',
  options: {
    baseValue: 5,
  },
})
  .extendApi(() => ({
    pluginMethod: () => 'plugin method',
  }))
  .extendEditorApi(({ getOptions }) => ({
    multiply: (factor: number) => getOptions().baseValue * factor,
  }))
  .extendTransforms(() => ({
    pluginTransform: () => {
      // 插件特定的转换
    },
  }))
  .extendEditorTransforms(({ editor }) => ({
    editorTransform: () => {
      // 编辑器特定的转换
    },
  }));

editor.api.myPlugin.api.pluginMethod();
editor.api.multiply(3);
editor.tf.myPlugin.pluginTransform();
editor.tf.editorTransform();
```

## 将Slate插件转换为Plate插件

要将类型化的Slate插件转换为Plate插件，可以使用`toPlatePlugin`：

```ts
const CodeBlockPlugin = toPlatePlugin(createSlatePlugin({ key: 'code_block' }), {
  handlers: {},
  options: { hotkey: ['mod+opt+8', 'mod+shift+8'] },
});
```